/*
 * Executor.c
 *
 *  Created on: 23/03/2011
 *      Author: luis
 */

#include "Executor.h"
#include "Constants.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void balance_arguments(Executor * executor){
	int length1 = strlen(executor->argument1);
	int length2 = strlen(executor->argument2);
	if (length2 < length1){
		int current_position = length2;
		while (current_position < length1){
			char a[2];
			a[0]=executor->argument2[0];
			a[1]='\0';
			strcat(executor->argument2, a);
			current_position++;
		}
	}
}

int is_in_string(char * argument, char c){
	int length = strlen(argument);
	int i;
	int found = 0;
	for (i=0; i<length && found == 0; i++){
		if (argument[i]==c){
			found = 1;
		}
	}
	return found;
}

int get_character_position(char * argument, char c){
	int length = strlen(argument);
	int i;
	int position = -1;
	//int found = 0;
	for (i=0; i<length /*&& found == 0*/; i++){
		if (argument[i]==c){
			//found = 1;
			position = i;
		}
	}
	return position;
}

void translate(Executor * executor){
	char c;
	while ((c = fgetc(stdin))!=EOF){
		if (!is_in_string(executor->argument1, c)){
			fputc(c, stdout);
		}
		else {
			int position = get_character_position(executor->argument1, c);
			fputc(executor->argument2[position], stdout);
		}
	}
}

void delete(Executor * executor){
	char c;
	while ((c = fgetc(stdin))!=EOF){
		if (!is_in_string(executor->argument1, c)){
			fputc(c, stdout);
		}
	}
}

void summarize(Executor * executor, int argument_to_use){
	char * argument;
	if (argument_to_use == 1){
		argument = executor->argument1;
	}
	else {
		argument = executor->argument2;
	}
	int * array = (int*)malloc(sizeof(int)*(strlen(argument)));
	int i;
	for (i=0; i<strlen(argument);i++){
		array[i] = 0;
	}
	char c;
	while ((c = fgetc(stdin))!=EOF){
		if (!is_in_string(argument, c)){
			fputc(c, stdout);
		}
		else {
			int position = get_character_position(argument, c);
			if (array[position] == 0){
				fputc(c, stdout);
				array[position] = 1;
			}
		}
	}
}

void translate_and_summarize(Executor * executor){
	int * array = (int*)malloc(sizeof(int)*(strlen(executor->argument2)));
	int i;
	for (i=0; i<strlen(executor->argument2);i++){
		array[i] = 0;
	}
	char c;
	while ((c = fgetc(stdin))!=EOF){
		if (!is_in_string(executor->argument1, c)){
			if (!is_in_string(executor->argument2, c)){
				fputc(c, stdout);
			}
			else {
				int position = get_character_position(executor->argument2, c);
				if (array[position] == 0){
					fputc(c, stdout);
					array[position] = 1;
				}
			}
		}
		else {
			int position = get_character_position(executor->argument1, c);
			if (array[position] == 0){
				if (array[position] == 0){
					fputc(executor->argument2[position], stdout);
					array[position] = 1;
				}
			}
		}
	}
}

void delete_and_summarize(Executor * executor){
	int * array = (int*)malloc(sizeof(int)*(strlen(executor->argument2)));
	int i;
	for (i=0; i<strlen(executor->argument2);i++){
		array[i] = 0;
	}
	char c;
	while ((c = fgetc(stdin))!=EOF){
		if (!is_in_string(executor->argument1, c)){
			if (!is_in_string(executor->argument2, c)){
				fputc(c, stdout);
			}
			else {
				int position = get_character_position(executor->argument2, c);
				if (array[position] == 0){
					fputc(c, stdout);
					array[position] = 1;
				}
			}
		}
	}
}

int executor_get_mode(Executor * executor){
	return executor->firstMode;
}

void executor_set_first_argument(Executor * executor, char * argument){
	executor->argument1 = argument;
}

void executor_set_second_argument(Executor * executor, char * argument){
	executor->argument2 = argument;
}

void executor_create(Executor * executor){
	executor->argument1 = "";
	executor->argument2 = "";
	executor->firstMode = UNDEFINED;
	executor->sndMode = UNDEFINED;
}

void executor_change_first_mode(Executor * executor, int mode){
	executor->firstMode = mode;
}

void executor_change_second_mode(Executor * executor, int mode){
	executor->sndMode = mode;
}

void executor_run(Executor * executor){
	if (executor->firstMode != UNDEFINED){
		if (executor->firstMode == TRANSLATE){
			balance_arguments(executor);
			if (executor->sndMode == SUMMARIZE){
				translate_and_summarize(executor);
			}
			else {
				translate(executor);
			}
		}
		if (executor->firstMode == SUMMARIZE){
			summarize(executor, 1);
		}
		if (executor->firstMode == DELETE){
			if (executor->sndMode == SUMMARIZE){
				delete_and_summarize(executor);
			}
			else {
				delete(executor);
			}
		}
	}
}

void executor_delete(Executor * executor){
	free (executor);
}
